package org.apache.ocean.merge;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class PluginManager {
	File libDirectory;
	Map<String, QueryPreprocessorProxy> map;

	public PluginManager(File libDirectory) {
		this.libDirectory = libDirectory;

	}

	public class JarLoader {
		public long lastModified;

	}

	public class JarInstance {
		ClassLoader contextClassLoader;

		public void loadJar(File file) throws Exception {
			contextClassLoader = Thread.currentThread().getContextClassLoader();
			URL jarURL = file.toURI().toURL();
			URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { jarURL }, contextClassLoader);
			List<String> classNames = toClassNames(file);
			for (String className : classNames) {
				Class clazz = Class.forName(className, true, urlClassLoader);
				//if (isQueryPreprocessor(clazz)) {

				//}
			}
		}

		

		public void loadInstance(Class clazz) throws Exception {
			Object object = clazz.newInstance();
			QueryPreprocessorProxy proxy = new QueryPreprocessorProxy(object);
			QueryPreprocessor queryPreprocessor = (QueryPreprocessor) Proxy.newProxyInstance(contextClassLoader, new Class[] { QueryPreprocessor.class }, proxy);

		}
	}

	public static void main(String[] args) {
		try {
			List<Class> classes = getClassesWithInterface("org.xmlpull.v1.XmlPullParser", new File("G:\\dev\\apache-solr-1.2.0\\lib\\xpp3-1.1.3.4.O.jar"));
			for (Class clazz : classes) {
				System.out.println(clazz.getName());
			}
			//toClassNames(new File("G:\\dev\\apache-solr-1.2.0\\lib\\commons-io-1.2.jar"));
		} catch (Throwable throwable) {
			throwable.printStackTrace();
		}
	}
  
	public static List<Class> getClassesWithInterface(String interfaceName, File file) throws Exception {
		ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
		URL jarURL = file.toURI().toURL();
		URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { jarURL }, contextClassLoader);
		List<String> classNames = toClassNames(file);
		List<Class> classes = new ArrayList<Class>();
		for (String className : classNames) {
			Class clazz = Class.forName(className, true, urlClassLoader);
			if (implementsInterface(clazz, interfaceName)) {
				classes.add(clazz);
			}
		}
		return classes;
	}
	
	public static boolean implementsInterface(Class clazz, String interfaceClassName) throws Exception {
		Class[] interfaceClasses = clazz.getInterfaces();
		if (interfaceClasses != null) {
			for (Class ic : interfaceClasses) {
				if (ic.getName().equals(interfaceClassName)) {
					return true;
				}
			}
		}
		return false;
	}
	
	public static List<String> toClassNames(File file) throws Exception {
		JarFile jarFile = new JarFile(file);
		List<JarEntry> jarEntries = Collections.list(jarFile.entries());
		List<String> classNames = new ArrayList<String>();
		for (JarEntry jarEntry : jarEntries) {
			if (!jarEntry.isDirectory()) {
				String filePath = jarEntry.getName();
				if (filePath.endsWith(".class") && filePath.indexOf('$') == -1) {
					filePath = filePath.replace('/', '.');
					String className = filePath.substring(0, filePath.lastIndexOf('.'));
					//System.out.println(className);
					classNames.add(className);
				}
			}
		}
		return classNames;
	}

	public List<QueryPreprocessor> getQueryPreprocessors() {
		return null;
	}

	public class QueryPreprocessorProxy implements InvocationHandler {
		private Object object;

		public QueryPreprocessorProxy(Object object) {
			this.object = object;
		}

		public void setObject(Object object) {
			if (object == null)
				throw new IllegalArgumentException("object null");
			this.object = object;
		}

		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			Object localObject = object;

			return null;
		}
	}
}
